using k8s;
using k8s.Models;
using Microsoft.Extensions.Logging;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

namespace SumerCoreDevOps.Infrastructure.Libraries;

/// <summary>
/// Kubernetes 操作库
/// </summary>
public class KubernetesLibrary
{
    private readonly ILogger<KubernetesLibrary> _logger;
    private readonly IKubernetes _k8sClient;

    /// <summary>
    /// 日志事件（消息，级别）
    /// </summary>
    public event Action<string, string>? OnLog;

    public KubernetesLibrary(ILogger<KubernetesLibrary> logger, string kubeConfigPath)
    {
        _logger = logger;
        var config = KubernetesClientConfiguration.BuildConfigFromConfigFile(kubeConfigPath);
        _k8sClient = new Kubernetes(config);
    }

    public KubernetesLibrary(ILogger<KubernetesLibrary> logger, string clusterUrl, string token)
    {
        _logger = logger;
        var config = new KubernetesClientConfiguration
        {
            Host = clusterUrl,
            AccessToken = token,
            SkipTlsVerify = true // 生产环境应配置证书
        };
        _k8sClient = new Kubernetes(config);
    }

    /// <summary>
    /// 记录日志并触发事件
    /// </summary>
    private void Log(string message, string level = "Info")
    {
        switch (level)
        {
            case "Info":
                _logger.LogInformation(message);
                break;
            case "Warning":
                _logger.LogWarning(message);
                break;
            case "Error":
                _logger.LogError(message);
                break;
            default:
                _logger.LogDebug(message);
                break;
        }

        OnLog?.Invoke(message, level);
    }

    /// <summary>
    /// 应用 YAML 清单
    /// </summary>
    public async Task<bool> ApplyManifestAsync(string yamlContent, string namespaceName = "default")
    {
        try
        {
            Log($"开始应用 K8s 清单到命名空间: {namespaceName}");

            var deserializer = new DeserializerBuilder()
                .WithNamingConvention(CamelCaseNamingConvention.Instance)
                .IgnoreUnmatchedProperties()
                .Build();

            // 支持多文档 YAML（用 --- 分隔）
            var documents = yamlContent.Split(new[] { "---" }, StringSplitOptions.RemoveEmptyEntries);
            var successCount = 0;
            var failCount = 0;

            foreach (var document in documents)
            {
                if (string.IsNullOrWhiteSpace(document))
                    continue;

                try
                {
                    // 解析 YAML 到字典以获取 kind 和 apiVersion
                    var resourceDict = deserializer.Deserialize<Dictionary<string, object>>(document);

                    if (resourceDict == null || !resourceDict.ContainsKey("kind"))
                    {
                        Log("跳过无效的 YAML 文档", "Warning");
                        continue;
                    }

                    var kind = resourceDict["kind"].ToString();
                    Log($"检测到资源类型: {kind}");

                    // 使用 K8s 客户端解析和应用资源
                    var applied = await ApplyResourceByKindAsync(document, kind!, namespaceName);

                    if (applied)
                        successCount++;
                    else
                        failCount++;
                }
                catch (Exception ex)
                {
                    Log($"应用单个 YAML 文档失败: {ex.Message}", "Error");
                    failCount++;
                }
            }

            Log($"K8s 清单应用完成: 成功 {successCount} 个, 失败 {failCount} 个");
            return failCount == 0;
        }
        catch (Exception ex)
        {
            Log($"应用 K8s 清单失败: {ex.Message}", "Error");
            return false;
        }
    }

    /// <summary>
    /// 根据资源类型应用资源
    /// </summary>
    private async Task<bool> ApplyResourceByKindAsync(string yamlContent, string kind, string namespaceName)
    {
        try
        {
            switch (kind)
            {
                case "Deployment":
                    var deployment = KubernetesYaml.Deserialize<V1Deployment>(yamlContent);
                    return await ApplyDeploymentAsync(deployment, namespaceName);

                case "Service":
                    var service = KubernetesYaml.Deserialize<V1Service>(yamlContent);
                    return await ApplyServiceAsync(service, namespaceName);

                case "ConfigMap":
                    var configMap = KubernetesYaml.Deserialize<V1ConfigMap>(yamlContent);
                    return await ApplyConfigMapAsync(configMap, namespaceName);

                case "Secret":
                    var secret = KubernetesYaml.Deserialize<V1Secret>(yamlContent);
                    return await ApplySecretAsync(secret, namespaceName);

                case "Namespace":
                    var ns = KubernetesYaml.Deserialize<V1Namespace>(yamlContent);
                    return await ApplyNamespaceAsync(ns);

                default:
                    Log($"不支持的资源类型: {kind}", "Warning");
                    return false;
            }
        }
        catch (Exception ex)
        {
            Log($"应用 {kind} 资源失败: {ex.Message}", "Error");
            return false;
        }
    }

    /// <summary>
    /// 应用 Deployment 资源
    /// </summary>
    private async Task<bool> ApplyDeploymentAsync(V1Deployment deployment, string namespaceName)
    {
        try
        {
            var name = deployment.Metadata.Name;
            deployment.Metadata.NamespaceProperty = namespaceName;

            try
            {
                await _k8sClient.AppsV1.ReadNamespacedDeploymentAsync(name, namespaceName);
                await _k8sClient.AppsV1.ReplaceNamespacedDeploymentAsync(deployment, name, namespaceName);
                Log($"更新 Deployment: {name}");
            }
            catch (k8s.Autorest.HttpOperationException ex) when (ex.Response.StatusCode == System.Net.HttpStatusCode.NotFound)
            {
                await _k8sClient.AppsV1.CreateNamespacedDeploymentAsync(deployment, namespaceName);
                Log($"创建 Deployment: {name}");
            }

            return true;
        }
        catch (Exception ex)
        {
            Log($"应用 Deployment 失败: {ex.Message}", "Error");
            return false;
        }
    }

    /// <summary>
    /// 应用 Service 资源
    /// </summary>
    private async Task<bool> ApplyServiceAsync(V1Service service, string namespaceName)
    {
        try
        {
            var name = service.Metadata.Name;
            service.Metadata.NamespaceProperty = namespaceName;

            try
            {
                await _k8sClient.CoreV1.ReadNamespacedServiceAsync(name, namespaceName);
                await _k8sClient.CoreV1.ReplaceNamespacedServiceAsync(service, name, namespaceName);
                Log($"更新 Service: {name}");
            }
            catch (k8s.Autorest.HttpOperationException ex) when (ex.Response.StatusCode == System.Net.HttpStatusCode.NotFound)
            {
                await _k8sClient.CoreV1.CreateNamespacedServiceAsync(service, namespaceName);
                Log($"创建 Service: {name}");
            }

            return true;
        }
        catch (Exception ex)
        {
            Log($"应用 Service 失败: {ex.Message}", "Error");
            return false;
        }
    }

    /// <summary>
    /// 应用 ConfigMap 资源
    /// </summary>
    private async Task<bool> ApplyConfigMapAsync(V1ConfigMap configMap, string namespaceName)
    {
        try
        {
            var name = configMap.Metadata.Name;
            configMap.Metadata.NamespaceProperty = namespaceName;

            try
            {
                await _k8sClient.CoreV1.ReadNamespacedConfigMapAsync(name, namespaceName);
                await _k8sClient.CoreV1.ReplaceNamespacedConfigMapAsync(configMap, name, namespaceName);
                Log($"更新 ConfigMap: {name}");
            }
            catch (k8s.Autorest.HttpOperationException ex) when (ex.Response.StatusCode == System.Net.HttpStatusCode.NotFound)
            {
                await _k8sClient.CoreV1.CreateNamespacedConfigMapAsync(configMap, namespaceName);
                Log($"创建 ConfigMap: {name}");
            }

            return true;
        }
        catch (Exception ex)
        {
            Log($"应用 ConfigMap 失败: {ex.Message}", "Error");
            return false;
        }
    }

    /// <summary>
    /// 应用 Secret 资源
    /// </summary>
    private async Task<bool> ApplySecretAsync(V1Secret secret, string namespaceName)
    {
        try
        {
            var name = secret.Metadata.Name;
            secret.Metadata.NamespaceProperty = namespaceName;

            try
            {
                await _k8sClient.CoreV1.ReadNamespacedSecretAsync(name, namespaceName);
                await _k8sClient.CoreV1.ReplaceNamespacedSecretAsync(secret, name, namespaceName);
                Log($"更新 Secret: {name}");
            }
            catch (k8s.Autorest.HttpOperationException ex) when (ex.Response.StatusCode == System.Net.HttpStatusCode.NotFound)
            {
                await _k8sClient.CoreV1.CreateNamespacedSecretAsync(secret, namespaceName);
                Log($"创建 Secret: {name}");
            }

            return true;
        }
        catch (Exception ex)
        {
            Log($"应用 Secret 失败: {ex.Message}", "Error");
            return false;
        }
    }

    /// <summary>
    /// 应用 Namespace 资源
    /// </summary>
    private async Task<bool> ApplyNamespaceAsync(V1Namespace ns)
    {
        try
        {
            var name = ns.Metadata.Name;

            try
            {
                await _k8sClient.CoreV1.ReadNamespaceAsync(name);
                await _k8sClient.CoreV1.ReplaceNamespaceAsync(ns, name);
                Log($"更新 Namespace: {name}");
            }
            catch (k8s.Autorest.HttpOperationException ex) when (ex.Response.StatusCode == System.Net.HttpStatusCode.NotFound)
            {
                await _k8sClient.CoreV1.CreateNamespaceAsync(ns);
                Log($"创建 Namespace: {name}");
            }

            return true;
        }
        catch (Exception ex)
        {
            Log($"应用 Namespace 失败: {ex.Message}", "Error");
            return false;
        }
    }

    /// <summary>
    /// 部署服务
    /// </summary>
    public async Task<bool> DeployServiceAsync(
        string serviceName,
        string imageName,
        string namespaceName = "default",
        int replicas = 1,
        Dictionary<string, string>? labels = null,
        Dictionary<string, string>? environmentVars = null)
    {
        try
        {
            Log($"开始部署服务: {serviceName} 到命名空间: {namespaceName}");

            var deployment = new V1Deployment
            {
                Metadata = new V1ObjectMeta
                {
                    Name = serviceName,
                    NamespaceProperty = namespaceName,
                    Labels = labels ?? new Dictionary<string, string>
                    {
                        ["app"] = serviceName
                    }
                },
                Spec = new V1DeploymentSpec
                {
                    Replicas = replicas,
                    Selector = new V1LabelSelector
                    {
                        MatchLabels = new Dictionary<string, string>
                        {
                            ["app"] = serviceName
                        }
                    },
                    Template = new V1PodTemplateSpec
                    {
                        Metadata = new V1ObjectMeta
                        {
                            Labels = new Dictionary<string, string>
                            {
                                ["app"] = serviceName
                            }
                        },
                        Spec = new V1PodSpec
                        {
                            Containers = new List<V1Container>
                            {
                                new V1Container
                                {
                                    Name = serviceName,
                                    Image = imageName,
                                    Env = environmentVars?.Select(kv => new V1EnvVar
                                    {
                                        Name = kv.Key,
                                        Value = kv.Value
                                    }).ToList()
                                }
                            }
                        }
                    }
                }
            };

            // 检查是否已存在
            try
            {
                var existing = await _k8sClient.AppsV1.ReadNamespacedDeploymentAsync(
                    serviceName,
                    namespaceName);

                // 更新现有部署
                await _k8sClient.AppsV1.ReplaceNamespacedDeploymentAsync(
                    deployment,
                    serviceName,
                    namespaceName);

                Log($"服务更新成功: {serviceName}");
            }
            catch (k8s.Autorest.HttpOperationException ex) when (ex.Response.StatusCode == System.Net.HttpStatusCode.NotFound)
            {
                // 创建新部署
                await _k8sClient.AppsV1.CreateNamespacedDeploymentAsync(
                    deployment,
                    namespaceName);

                Log($"服务部署成功: {serviceName}");
            }

            return true;
        }
        catch (Exception ex)
        {
            Log($"部署服务失败: {serviceName} - {ex.Message}", "Error");
            return false;
        }
    }

    /// <summary>
    /// 获取服务状态
    /// </summary>
    public async Task<string> GetServiceStatusAsync(string serviceName, string namespaceName = "default")
    {
        try
        {
            var deployment = await _k8sClient.AppsV1.ReadNamespacedDeploymentAsync(
                serviceName,
                namespaceName);

            var status = deployment.Status;
            var availableReplicas = status.AvailableReplicas ?? 0;
            var desiredReplicas = status.Replicas ?? 0;

            if (availableReplicas == desiredReplicas && desiredReplicas > 0)
            {
                return "Running";
            }
            else if (availableReplicas > 0)
            {
                return $"Partial ({availableReplicas}/{desiredReplicas})";
            }
            else
            {
                return "NotReady";
            }
        }
        catch (Exception ex)
        {
            Log($"获取服务状态失败: {serviceName} - {ex.Message}", "Error");
            return "Error";
        }
    }

    /// <summary>
    /// 删除服务
    /// </summary>
    public async Task<bool> DeleteServiceAsync(string serviceName, string namespaceName = "default")
    {
        try
        {
            Log($"删除服务: {serviceName} 从命名空间: {namespaceName}");

            await _k8sClient.AppsV1.DeleteNamespacedDeploymentAsync(
                serviceName,
                namespaceName);

            Log($"服务删除成功: {serviceName}");
            return true;
        }
        catch (Exception ex)
        {
            Log($"删除服务失败: {serviceName} - {ex.Message}", "Error");
            return false;
        }
    }

    /// <summary>
    /// 获取 Pod 日志
    /// </summary>
    public async Task<string> GetPodLogsAsync(
        string podName,
        string namespaceName = "default",
        int tailLines = 100)
    {
        try
        {
            var logsStream = await _k8sClient.CoreV1.ReadNamespacedPodLogAsync(
                podName,
                namespaceName,
                tailLines: tailLines);

            using var reader = new StreamReader(logsStream);
            return await reader.ReadToEndAsync();
        }
        catch (Exception ex)
        {
            Log($"获取 Pod 日志失败: {podName} - {ex.Message}", "Error");
            return string.Empty;
        }
    }
}
